package cn.lizemin.fakedata;

import com.google.common.collect.Lists;
import org.junit.jupiter.api.Test;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 李泽民
 * @Date 2024/2/18 15:57
 * @Description
 */
public class Demo {

    @Test
    public void test_stream() {
        ArrayList<Integer> nums = Lists.newArrayList(1, 1, 2, 3, 1);

//        List<Integer> result = nums.stream().distinct().collect(Collectors.toList());
//        System.out.println(result);

        HashSet<Integer> res2 = new HashSet<>(nums);
        System.out.println(res2);
    }

    @Test
    public void test_hashcode() {
        for (int i = 0; i < 10; i++) {
            Teacher tea = new Teacher("李泽民", 28);
            System.out.println(Objects.hashCode(tea));
        }
    }

    @Test
    public void test_hashmap() {
        HashSet<Teacher> teachers = new HashSet<>();
        Teacher tea = new Teacher("李泽民", 28);
        Teacher tea2 = new Teacher("李泽民", 28);
        teachers.add(tea);
        teachers.add(tea2);
        System.out.println(teachers);
    }

    @Test
    public void test_hashmap2() {
        HashMap<String, Integer> hm = new HashMap<>(16, 0.8F);

    }

    @Test
    public void test_reentrantLock() {
        ReentrantLock lock = new ReentrantLock();
//        lock.lockInterruptibly();
//        lock.isLocked()


    }

    @Test
    public void test_arr() {
        int[] arr = {12, 8, 25, 6, 10};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    private static int count = 1;

    @Test
    public void test_print() throws InterruptedException {
        Runnable task = () -> {
            while (count <= 100) {
                synchronized (this) {
                    this.notifyAll();
                    System.out.println(Thread.currentThread().getName() + " ==> " + count);
                    count++;
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        new Thread(task, "t1").start();
        new Thread(task, "t2").start();
        TimeUnit.SECONDS.sleep(3);
    }

    @Test
    public void test_heap_overflow() {
        ArrayList<int[]> nums = new ArrayList<>();
        while (true) {
            nums.add(new int[1024 * 1024]);
        }
    }

    @Test
    public void test_stack_overflow() {
        play();
    }


    private void play() {
        play();
    }

    @Test
    public void test_use_thread_local() {
        ThreadLocal<String> local = new ThreadLocal<>();
        local.set("熊大");
        String name = "熊二";
        local.set(name);
        System.out.println(local.get());
        new Thread(() -> System.out.println(local.get())).start();
    }

    @Test
    public void test_use_inheritable_local() {
        ThreadLocal<String> local = new InheritableThreadLocal<>();
        local.set("熊大");
        String name = "熊二";
        local.set(name);
        System.out.println(local.get());
        new Thread(() -> System.out.println(local.get())).start();
    }

    @Test
    public void test_use_map() {
        HashMap<String, String> map = new HashMap<>();
        map.put("name", null);
        System.out.println(map.get("name"));
        System.out.println(map.containsKey("name"));
        System.out.println(map.containsValue(null));
    }

    @Test
    public void test_use_concurrent_map() {
        ConcurrentMap<String, String> map = new ConcurrentHashMap<>();
        map.put("name", "null");
        System.out.println(map.get("name"));
        System.out.println(map.containsKey("name"));
        System.out.println(map.containsValue("null"));
    }

    @Test
    public void test_thread_state() throws InterruptedException {
        Thread t = new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getState());
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        t.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println(t.getState());
        TimeUnit.SECONDS.sleep(5);
    }

    @Test
    public void test_interrupt() throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        TimeUnit.SECONDS.sleep(2);
        thread.interrupt();
        System.out.println("线程已中断");
        TimeUnit.SECONDS.sleep(4);
    }

    @Test
    public void test_thread_pool() throws InterruptedException {
//        ExecutorService pool = Executors.newCachedThreadPool();
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
        pool.scheduleAtFixedRate(() -> {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }, 2, 1, TimeUnit.SECONDS);
        TimeUnit.SECONDS.sleep(15);
    }

    @Test
    public void test_reentrantLock2() {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
//        condition.await();
        LockSupport.park();
    }

    @Test
    public void test_array_max() {
        List<Integer> nums = Arrays.asList(12, 6, 18, 9);
        System.out.println(nums.stream().max(Integer::compare).get());
    }

    @Test
    public void test_dead_lock() throws InterruptedException {
        Object lockA = new Object();
        Object lockB = new Object();
        Runnable task1 = () -> {
            synchronized (lockA) {
                System.out.println(Thread.currentThread().getName() + "抢到了锁A");
                try {
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println(Thread.currentThread().getName() + "执行完A任务");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (lockB) {
                    System.out.println(Thread.currentThread().getName() + "抢到了锁B");
                }
            }
        };
        Runnable task2 = () -> {
            synchronized (lockB) {
                System.out.println(Thread.currentThread().getName() + "抢到了锁B");
                try {
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println(Thread.currentThread().getName() + "执行完B任务");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (lockA) {
                    System.out.println(Thread.currentThread().getName() + "抢到了锁A");
                }
            }
        };
        Thread t1 = new Thread(task1, "t1");
        Thread t2 = new Thread(task2, "t2");
        t1.start();
        t2.start();
        TimeUnit.SECONDS.sleep(60);
    }

    @Test
    public void test_use_collections(){
        ArrayList<Integer> nums = Lists.newArrayList(82, 22, 98);
        System.out.println(Collections.max(nums));
    }

    @Test
    public void test_use_hash_table(){
        Hashtable<String, String> ht = new Hashtable<>();
        ht.put("name", null);
        System.out.println(ht);
    }

    @Test
    public void test_arrays(){
        int[] arr = {1, 12, 5};
        int[] arr2 = {1, 12, 5};
        System.out.println(Arrays.equals(arr, arr2));
    }

    @Test
    public void test_use_stack(){
        Stack<Integer> nums = new Stack<>();
//        nums.add(22);
//        nums.add(12);
        System.out.println(nums.pop());

    }

    @Test
    public void test_use_queue(){
        ArrayDeque<Integer> queue = new ArrayDeque<>();
//        queue.add(12);
        System.out.println(queue.remove());

    }

    @Test
    public void test_use_hash_set(){
        HashSet<Integer> hs = new HashSet<>();
        System.out.println(hs.add(12));
        System.out.println(hs.add(12));
    }


}
